﻿CMAKE_LIST_TEMPLATE = [[cmake_minimum_required(VERSION 3.8)
project("%s")

set(TARGET_NAME	%s)

# include_directories(<HEADER_PATH>)

%s

# add_compile_options(<COMPILER_FLAGS>)

aux_source_directory(./ SOURCE_FILES)

add_executable(${TARGET_NAME} ${SOURCE_FILES})

# target_precompile_headers(${TARGET_NAME} PRIVATE pch_header.h)

# target_link_libraries(${TARGET_NAME}
#	<LIB_NAME>
# )
]];

local CMAKE_LIST_TEMPLATE_LIB = [[cmake_minimum_required(VERSION 3.8)
project("%s")

set(TARGET_NAME	%s)

# include_directories(<HEADER_PATH>)

%s

# add_compile_options(<COMPILER_FLAGS>)

aux_source_directory(./ SOURCE_FILES)

add_library(${TARGET_NAME} %s ${SOURCE_FILES})

# target_precompile_headers(${TARGET_NAME} PRIVATE pch_header.h)

# target_link_libraries(${TARGET_NAME}
#	<LIB_NAME>
# )
]];

function create_cmake_project(path, name, default_tool, default_config, main_file_content, subsystem)
	utils:mkdir(path);
	local function write_file(file_name, content)
		local cmake_file = io.open(make_path(path, file_name), "w+");
		cmake_file:write(content);
		cmake_file:close();
	end;
	local linker_options_win32 = [[if(MSVC)
	add_link_options(/subsystem:windows)
else()
	add_link_options(-mwindows)
endif()]];

	local linker_options = [[# add_link_options(<LINKER_FLAGS>)]];
	if subsystem == "win32" or subsystem == "shared lib" then
		linker_options = linker_options_win32;
	end;
	local cmake_list_template = CMAKE_LIST_TEMPLATE;
	
	local lib_type = nil;
	if subsystem == "static lib" then
		lib_type = "STATIC";
		cmake_list_template = CMAKE_LIST_TEMPLATE_LIB;
	elseif subsystem == "shared lib" then
		lib_type = "SHARED";
		cmake_list_template = CMAKE_LIST_TEMPLATE_LIB;
	end;
	write_file("CMakeLists.txt", string.format(cmake_list_template, name, name, linker_options, lib_type));
	if main_file_content then
		write_file("main.cpp", main_file_content.."\n");
	end;
	if default_tool then
		write_file("settings.lua", string.format([[project_configs = {[".build"] = {config = "%s"; toolset = "%s";};};]], default_config, default_tool));
	end;
end;

function project_wizard:on_init()
	self:init_icons({ "group unfolded", "group folded", "terminal", "exe file", "lib file", "dll file", "register"});
	local project_types = {
		{
			{LANG("dialog/project_wizard/type/native"),"native"},
			{LANG("dialog/project_wizard/type/console"), "console", 3},
			{LANG("dialog/project_wizard/type/win32"), "win32", 4},
			{LANG("dialog/project_wizard/type/static"), "static lib", 5},
			{LANG("dialog/project_wizard/type/shared"), "shared lib", 6},
		};
	};
	local has_wsl = false;
	local has_esp32 = ESP32_IDF_TOOLSET ~= nil;
	for idx, tool in ipairs(TOOLSETS) do
		if tool["target"] == "wsl" then
			if not has_wsl then
				self.__wsl_toolset = tool.name;
			end;
			has_wsl = true;
		end;
	end;
	if has_wsl then
		table.insert(project_types, {
				{LANG("dialog/project_wizard/type/wsl"), "wsl"},
				{LANG("dialog/project_wizard/type/console"), "console", 3},
				{LANG("dialog/project_wizard/type/static"), "static lib", 5},
				{LANG("dialog/project_wizard/type/shared"), "shared lib", 6},
		});
	end;
	if has_esp32 then
		table.insert(project_types,	{
				{LANG("dialog/project_wizard/type/esp32"), "esp32"},
				{"ESP32", "esp32", 7},
				{"ESP32S2", "esp32s2", 7},
				{"ESP32S3", "esp32s3", 7},
				{"ESP32C2", "esp32c2", 7},
				{"ESP32C3", "esp32c3", 7},
		});
	end;
	self:init_wizard(project_types);
	self:select("native", "console");
end;
function project_wizard:on_project_type_changed(name, group)
	-- print("on_project_type_changed(", name, ",", group, ")");
	-- self:set_info("INFO "..name..","..group);
	return 1;
end;

function project_wizard:on_dismissed()
	return 1;
end;

function project_wizard:do_create(info)
	local file_content_map = {
		["wsl"] = {
			["console"] = [[#include <stdio.h>
int main() {
	printf("hello world\n");
	return 0;
}]];
			["shared lib"] = [[#include <stdio.h>
int foo() {
	printf("hello world\n");
	return 0;
}]];
			["static lib"] = [[#include <stdio.h>
int foo() {
	printf("hello world\n");
	return 0;
}]];
		};
		["native"] = {
			["console"] = [[#include <stdio.h>
int main() {
	printf("hello world\n");
	return 0;
}]];
			["win32"] = [[#include <windows.h>
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {
	MessageBoxA(0, "hello world\n", 0, MB_OK);
	return 0;
}]];
			["shared lib"] = [[#include <windows.h>
BOOL WINAPI DllMain(
	HINSTANCE hinstDLL,  // handle to DLL module
	DWORD fdwReason,     // reason for calling function
	LPVOID lpReserved )  // reserved
{
	// Perform actions based on the reason for calling.
	switch( fdwReason ) {
		case DLL_PROCESS_ATTACH:
			// Initialize once for each new process.
			// Return FALSE to fail DLL load.
			break;

		case DLL_THREAD_ATTACH:
			// Do thread-specific initialization.
			break;

		case DLL_THREAD_DETACH:
			// Do thread-specific cleanup.
			break;

		case DLL_PROCESS_DETACH:
			// Perform any necessary cleanup.
			break;
	}
	return TRUE;  // Successful DLL_PROCESS_ATTACH.
}]];
			["static lib"] = [[#include <stdio.h>
int foo() {
	printf("hello world\n");
	return 0;
}]];
		};
	};
	
	local proj_type = info["type"];
	local proj_type_group = info["group"];
	local proj_name = info["name"];
	local proj_path = info["path"];
	if utils:file_time(make_path(proj_path, "CMakeLists.txt")) then
		self:show_tip("path", LANG("dialog/project_wizard/project_exists"));
		return 0;
	end;
	if proj_type_group == "esp32" then
		project_wizard:enable(false);
		esp32_idf_create_project(ESP32_IDF_TOOLSET, proj_path, proj_name, proj_type,
			function(success)
				if success then
					project_wizard:dismiss();
					lsp:terminate();
					menu_bar:enable_cmake_menu_items();
					xws_mgr:load_xws(proj_path);
				else
					project_wizard:enable(true);
				end;
			end
		);
		return 1;
	end;
	if proj_type_group == "wsl" then
		create_cmake_project(proj_path, proj_name, self.__wsl_toolset, "Debug", file_content_map[proj_type_group][proj_type], proj_type);
	elseif proj_type_group == "native" then
		create_cmake_project(proj_path, proj_name, nil, "Debug", file_content_map[proj_type_group][proj_type], proj_type);
	end;
	project_wizard:dismiss();
	lsp:terminate();
	menu_bar:enable_cmake_menu_items();
	xws_mgr:load_xws(proj_path);
	return 1;
end;
